package net.alpenviewer.client.ui;

import com.google.gwt.maps.client.MapOptions;
import com.google.gwt.maps.client.MapType;
import com.google.gwt.maps.client.MapUIOptions;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.event.MapDragHandler;
import com.google.gwt.maps.client.event.MapMoveHandler;
import com.google.gwt.maps.client.event.MapZoomEndHandler;
import com.google.gwt.maps.client.geom.LatLng;

public final class MapModel {

	private static MapModel instance;

	public static synchronized MapModel getInstance() {
		if (instance == null) {
			instance = new MapModel();
		}
		return instance;
	}

	/* ********************* */

	private final MapWidget map;
	private final MapWidget earth;

	private MapModel() {
		final LatLng latLng = LatLng.newInstance(47.504214, 9.747620);
		final int zoom = 12;
		map = initMapWidget(latLng, zoom);
		earth = initEarthWidget(latLng, zoom);

		// consistent move
		map.addMapDragHandler(new MapDragHandler() {
			@Override public void onDrag(MapDragEvent event) {
				earth.setCenter(event.getSender().getCenter());
			}
		});
		earth.addMapMoveHandler(new MapMoveHandler() {
			@Override public void onMove(MapMoveEvent event) {
				map.setCenter(event.getSender().getCenter());
			}
		});
		// consistent zoom
		map.addMapZoomEndHandler(new MapZoomEndHandler() {
			@Override public void onZoomEnd(MapZoomEndEvent event) {
				earth.setZoomLevel(event.getNewZoomLevel());
				earth.setCenter(event.getSender().getCenter());
			}
		});
		earth.addMapZoomEndHandler(new MapZoomEndHandler() {
			@Override public void onZoomEnd(MapZoomEndEvent event) {
				map.setZoomLevel(event.getNewZoomLevel());
				map.setCenter(event.getSender().getCenter());
			}
		});

	}

	private static MapWidget initMapWidget(LatLng latLng, int zoom) {

		MapWidget mapWidget = new MapWidget(latLng, zoom, MapOptions.newInstance());

		MapUIOptions opts = mapWidget.getDefaultUI();

		opts.setNormalMapType(true);
		opts.setPhysicalMapType(true);
		opts.setSatelliteMapType(false);
		opts.setHybridMapType(false);

		opts.setDoubleClick(true);
		opts.setKeyboard(true);
		opts.setScrollwheel(true);

		opts.setLargeMapControl3d(true);
		opts.setMenuMapTypeControl(true);
		opts.setScaleControl(true);

		mapWidget.setUI(opts);

		mapWidget.setCurrentMapType(MapType.getPhysicalMap());
		// overview map delivers no move/drag events.
		/* mapWidget.addControl(new OverviewMapControl()); */

		// this may fail to layout the initial size. We will set the size later
		// (deferred)
		/* mapWidget.setSize("100%", "100%"); */

		return mapWidget;
	}

	private static MapWidget initEarthWidget(LatLng latLng, int zoom) {

		final MapWidget earthWidget = new MapWidget(latLng, zoom, MapOptions.newInstance());

		// add only what we want. e.g. Terrain
		earthWidget.addMapType(MapType.getEarthMap());
		earthWidget.setCurrentMapType(MapType.getEarthMap());		
		
		// this may fail to layout the initial size. We will set the size later
		// (deferred)
		/* mapWidget.setSize("100%", "100%"); */

		return earthWidget;
	}

	public MapWidget getMap() {
		return map;
	}

	public MapWidget getEarth() {
		return earth;
	}	

}
